<template>
    <div
        :class="['w-full text-20 p-24 box-border', { 'min-loading-height': isLoading }]"
        v-loading="isLoading"
        element-loading-text="加载中....."
    >
        <template v-if="!isLoading">
            <PageHeader title="会员分析" :is-data-loading="isLoading" @refresh="resetList"/>
            <!-- 顶部四条数据 -->
            <div class="w-full flex-between-items-box">
                <div
                    class="quantity-show flex card-style common-shadow px-24"
                    v-for="(item, index) in quantityData"
                    :key="index"
                >
                    <i :class="['iconfont', item.icon]" :style="{ color: item.color }"/>
                    <div class="flex-col-box justify-around ml-20 w-full">
                        <div class="font-900 flex-between-box w-full">
                            <div class="text-30">{{ item.num }}</div>
                            <!-- 提示图标 -->
                            <template v-if="item.content">
                                <el-popover
                                    placement="bottom"
                                    trigger="click"
                                    :content="item.content"
                                    :width="item.width"
                                >
                                    <template #reference>
                                        <Icon name="Warning" :size="18" class="text-t-secondary cursor-pointer"/>
                                    </template>
                                </el-popover>
                            </template>
                        </div>
                        <div class="text-18 mt-6 text-t-default">{{ item.name }}</div>
                    </div>
                </div>
            </div>
            <!-- 图标数据 -->
            <div class="w-full flex-between-box flex-wrap">
                <!-- 第二层 -->
                <div class="second-container-left mr-24 echarts-box">
                    <EChartsContainer title="会员地区分布" :options="mapOptions" id="mapECharts"/>
                </div>
                <div class="second-container-right">
                    <div class="common-box echarts-box">
                        <EChartsContainer title="会员地区人数排行榜" :custom="true">
                            <div class="mt-16 flex-col-box">
                                <div
                                    class="rank w-full flex-items-box my-16 justify-between pr-20"
                                    v-for="(item, index) in mapRanking"
                                    :key="item"
                                >
                                    <div class="flex-items-box">
                                        <template v-if="index < 3">
                                            <img :src="useImage('memberAnalysis', `${index + 1}.png`)" alt=""/>
                                        </template>
                                        <template v-else>
                                            <div class="rank-order rounded-full text-20 flex-center-box">{{ index + 1 }}</div>
                                        </template>
                                        <span class="ml-20 text-18 text-t-default">{{ item.name }}</span>
                                    </div>
                                    <span :class="['font-700 rank-num', { 'text-22' : index < 3 }]">{{ item.value }}</span>
                                </div>
                            </div>
                        </EChartsContainer>
                    </div>
                </div>
                <!-- 第三层 -->
                <div class="w-full flex-between-box">
                    <div class="third-container-side echarts-box">
                        <EChartsContainer title="会员状态分布" :options="statusOptions" id="statusECharts"/>
                    </div>
                    <div class="third-container-side echarts-box">
                        <EChartsContainer title="会员性别分布" :options="sexOptions" id="sexECharts"/>
                    </div>
                    <div class="third-container-side echarts-box-age-prop">
                        <EChartsContainer
                            title="会员年龄段占比"
                            :isLeft="true"
                            :options="agePropOptions"
                            id="agePropECharts"
                        />
                    </div>
                    <div class="third-container-side echarts-box">
                        <EChartsContainer title="会员标签分布" :custom="true">
                            <div class="p-24 h-full relative">
                                <div
                                    v-for="item in labelData"
                                    :key="item.name"
                                    class="flex-items-box justify-center absolute"
                                    :style="{
                                        fontSize: `${item.fontSize}px`,
                                        top: `${item.top}px`,
                                        left: `${item.left}px`,
                                        color: item.color
                                    }"
                                >
                                    {{ item.name }}
                                </div>
                            </div>
                        </EChartsContainer>
                    </div>
                </div>
                <!-- 第四层 -->
                <div class="w-full flex-between-box">
                    <div class="fourth-container-side echarts-box">
                        <EChartsContainer title="近 7 日会员增量变化" :options="sevenDayAddOptions" id="sevenDayChangeECharts"/>
                    </div>
                    <div class="fourth-container-side echarts-box">
                        <EChartsContainer title="近一年会员总量变化" :options="yearChangeOptions" id="yearChangeECharts"/>
                    </div>
                </div>
            </div>
        </template>
    </div>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import { cloneDeep } from 'lodash'
import { MonthEnum } from '@/type/common'
import { getRndInteger, timeout, useImage } from '@utils/methods'
import { AreaData, httpMemberAnalysis, SexData } from '@api/module/memberManage'
import dayjs from 'dayjs'
import EChartsContainer from '@components/EChartsContainer/index.vue'
import PageHeader from '@/components/PageHeader/index.vue'
import Icon from '@/components/Icon/index.vue'

// 是否加载中
const isLoading = ref(true)

// 顶部数据
interface QuantityData {
    /** @description 数据 */
    num: string | number
    /** @description 描述 */
    name: string
    /** @description icon 图标 */
    icon: string
    /** @description 图标色 */
    color: string
    /** @description 描述文本 */
    content: string
    /** @description 宽度 */
    width?: number
}

// 顶部数据展示
const quantityData = ref<QuantityData[]>([
    {
        num: '--',
        name: '会员总数',
        icon: 'icon-huiyuan',
        color: '#F7931A',
        content: '当前会员总数量（已删除将不计入）',
        width: 250
    },
    {
        num: '--',
        name: '近 7 日新增会员人数',
        icon: 'icon-shuliangbiandongtongji',
        color: '#FF6803',
        content: ''
    },
    {
        num: '--',
        name: '会员活跃人数占比',
        icon: 'icon-huoyueshijianduan',
        color: '#4A8CDA',
        content: '活跃人数在总会员人数中的占比',
        width: 230
    },
    {
        num: '--',
        name: '7 日新增会员消费比例',
        icon: 'icon-w_bili',
        color: '#70B944',
        content: '7 日内新增的会员中再次进行消费的人数占比',
        width: 280
    }
])

// 临时函数，进行百分比取数
const numFun = (total: number, prop: number) => Number((total * (prop / 100)).toFixed(0))

// 近 7 日会员总量变化
const sevenDayAddOptions = ref({})
// 近一年会员总量变化
const yearChangeOptions = ref({})

// 会员年龄段占比
const agePropOptions = ref({})
// 标签列表
const labelList: string[] = [
    '二次元', '九零后', '热爱', '小众化', '年轻', '团购', '代名词', '佛系', '运动', '吃货',
    '垮掉', '个性', '发际线', '阅读', '熬夜', '可乐', '游戏', '代码', '计算机', '消费',
    '购买', '单身', '高活跃', '美妆', '吃肉', '汉服', '机车', '单身', '年轻', '技术',
    '日常', '火锅'
]
// 会员标签数据
const labelData: Record<string, any>[] = reactive([])

// 盒子宽 700 高 330
const boxWidth = 370 - 50
const labelPosition = [
    { top: 120, left: boxWidth / 2 - 40, fontSize: 38 }, { top: 100, left: 40, fontSize: 32 },
    { top: 175, left: 110, fontSize: 22 }, { top: 80, left: 50, fontSize: 18 },
    { top: 125, left: 230, fontSize: 20 }, { top: 83, left: 200, fontSize: 18 },
    { top: 60, left: 180, fontSize: 22 }, { top: 100, left: 175, fontSize: 20 },
    { top: 100, left: 137, fontSize: 16 }, { top: 175, left: 200, fontSize: 22 },
    { top: 105, left: 225, fontSize: 15 }, { top: 200, left: 75, fontSize: 20 },
    { top: 75, left: 120, fontSize: 16 }, { top: 170, left: 160, fontSize: 15 },
    { top: 55, left: 245, fontSize: 20 }, { top: 210, left: 215, fontSize: 18 },
    { top: 200, left: 180, fontSize: 20 }, { top: 140, left: 80, fontSize: 16 },
    { top: 165, left: 30, fontSize: 25 }, { top: 250, left: 145, fontSize: 16 },
    { top: 180, left: 290, fontSize: 15 }, { top: 90, left: 265, fontSize: 14 },
    { top: 155, left: 110, fontSize: 20 }, { top: 205, left: 125, fontSize: 25 },
    { top: 233, left: 102, fontSize: 20 }, { top: 150, left: 275, fontSize: 15 },
    { top: 45, left: 90, fontSize: 22 }, { top: 235, left: 195, fontSize: 20 },
    { top: 36, left: 145, fontSize: 19 }, { top: 170, left: 246, fontSize: 18 },
    { top: 200, left: 250, fontSize: 18 }, { top: 142, left: 45, fontSize: 14 }
]

// 初始化标签
const initLabelData = () => {
    labelList.forEach((item, index) => {
        const colorArr: string[] = [
            '#F16868', '#3BA272', '#73C0DE', '#FAC858',
            '#5470C6', '#FC8331', '#B5DFE8', '#FA81AC',
            '#41B883', '#9A9A9A', '#E34942', '#FB9973'
        ]
        const { top = 10, left = 10, fontSize = 14 } = labelPosition[index] || {}
        labelData.push({
            top,
            left,
            fontSize,
            name: labelList[index],
            color: colorArr[getRndInteger(0, colorArr.length - 1)]
        })
    })
}

initLabelData()

setTimeout(async () => {
    await timeout(500)
    await nextTick()
    // 总人数
    const total = 113
    // 近7日新增会员量
    const newAddNum = 63
    // echarts 数据
    const { sevenDayAddData, yearChangeData, agePropData } = {
        sevenDayAddData: [
            numFun(newAddNum, 7),
            numFun(newAddNum, 13),
            numFun(newAddNum, 27),
            numFun(newAddNum, 15),
            numFun(newAddNum, 7),
            numFun(newAddNum, 20),
            numFun(newAddNum, 11)
        ],
        yearChangeData: [
            numFun(total, 0),
            numFun(total, 0),
            numFun(total, 0),
            numFun(total, 0),
            numFun(total, 0),
            numFun(total, 6),
            numFun(total, 18),
            numFun(total, 42),
            numFun(total, 57),
            numFun(total, 76),
            numFun(total, 101),
            numFun(total, 113)
        ],
        agePropData: [14, 42, 20, 12, 8, 4]
    }
    /**
     * 近 7 日会员增量变化
     * */
    // 近 7 日日期
    const sevenDay = []
    for (let day = 0; day <= 6; day++) {
        sevenDay.push(dayjs().subtract(day, 'day').format('MM-DD'))
    }
    sevenDayAddOptions.value = {
        // 提示框
        tooltip: {
            trigger: 'item'
        },
        xAxis: {
            type: 'category',
            data: sevenDay.reverse()
        },
        yAxis: {
            type: 'value',
            splitLine: {
                lineStyle: {
                    type: 'dashed'
                }
            }
        },
        series: [
            {
                data: sevenDayAddData.reverse(),
                type: 'line'
            }
        ]
    }

    /**
     * 近一年会员总量变化
     * */
    // 近一年月份
    const months = []
    for (let month = 0; month <= 11; month++) {
        months.push(MonthEnum[Number(dayjs().subtract(month, 'month').format('M'))])
    }
    yearChangeOptions.value = {
        // 提示框
        tooltip: {
            trigger: 'item'
        },
        xAxis: {
            type: 'category',
            data: months.reverse()
        },
        yAxis: {
            type: 'value',
            // 修改分割线样式
            splitLine: {
                lineStyle: {
                    type: 'dashed'
                }
            }
        },
        series: [
            {
                data: yearChangeData,
                type: 'line',
                name: '会员总量',
                smooth: true
            }
        ]
    }
    //
    // /**
    //  * 会员年龄占比
    //  * */
    const agePropName: Record<string, string | number>[] = [
        { name: '18以下' },
        { name: '18-25' },
        { name: '26-30' },
        { name: '31-35' },
        { name: '36-40' },
        { name: '40以上' }
    ]
    agePropName.forEach((item, index) => {
        item.value = agePropData[index]
    })
    agePropOptions.value = {
        // 提示框
        tooltip: {
            trigger: 'item',
            // 格式化提示值
            valueFormatter(value: number) {
                return `${value}%`
            }
        },
        series: [
            {
                name: '年龄占比',
                // 饼图
                type: 'pie',
                // 中间圆的大小、整体圆的大小
                radius: [65, 115],
                // 距离左端和上端的位置
                center: ['50%', '50%'],
                // 展示模式 - 扇形圆心角展现 radius
                // 每一段扇形的圆角
                itemStyle: {
                    borderRadius: 10,
                    borderColor: '#FFF',
                    borderWidth: 5
                },
                data: agePropName
            }
        ]
    }
}, 200)

// 刷新数据
const resetList = () => {
    console.log('111')
}

// 获取会员分析数据
const getMemberAnalysisData = () => {
    // 获取会员分析数据
    httpMemberAnalysis().then(async ({ data }) => {
        await timeout(500)
        isLoading.value = false
        await nextTick()
        // 会员总数
        quantityData.value[0].num = data.memberTotal
        quantityData.value[1].num = 63
        quantityData.value[2].num = '28%'
        quantityData.value[3].num = '17%'
        // 初始化地图
        initMap(data.areaData)
        // 初始化会员性别
        initMemberGender(data.sexData)
        // 初始化会员状态
        initMemberStatus()
    })
}

getMemberAnalysisData()

/**
 * 会员地区分布、地区人数排行榜
 * */
// 会员地区分布
const mapOptions = ref({})
// 会员地区排行榜
const mapRanking = ref<any[]>([])
// 初始化地图
const initMap = (areaList: AreaData[]) => {
    // 过滤人数大于 0 的数据
    const mapData = areaList.filter(({ regionMemberNum }) => Boolean(regionMemberNum)).map(({ regionName, regionMemberNum }) => ({
        name: regionName,
        value: regionMemberNum
    }))
    mapOptions.value = {
        tooltip: {
            trigger: 'item',
            valueFormatter(value: number) {
                return value ? `${value} 人` : '--'
            }
        },
        // 图例
        visualMap: {
            type: 'continuous',
            min: 0,
            max: areaList[0].regionMemberNum,
            text: ['Max', 'Min'],
            // 是否显示拖拽手柄
            calculable: false,
            inRange: {
                color: ['#B8E2EA', '#323A97']
            }
        },
        // 要显示的散点数据
        series: [
            {
                type: 'map',
                map: 'china',
                name: '会员数量',
                zoom: 1.2,
                data: mapData
            }
        ]
    }
    mapRanking.value = cloneDeep(mapData).splice(0, 10)
}

/**
 * 会员性别
 * */
// 会员性别分布
const sexOptions = ref({})
const initMemberGender = (sexData: SexData[]) => {
    // 会员总数
    const memberTotal = <number>quantityData.value[0].num
    sexOptions.value = {
        tooltip: {
            trigger: 'item',
            valueFormatter(value: number) {
                return `${value}人 ${((value * 100) / memberTotal).toFixed(0)}%`
            }
        },
        // 设置数据说明的垂直水平位置
        legend: {
            top: '4%',
            left: 'center'
        },
        // 数据填充色
        color: ['#A3D0E9', '#E6779F'],
        series: [
            {
                type: 'pie',
                // 组件上边距
                top: '8%',
                name: '人数占比',
                // 饼图内外边距
                radius: ['0', '80%'],
                // 图形样式 - 图形边框
                itemStyle: {
                    borderRadius: 8,
                    borderColor: '#FFF',
                    borderWidth: 8
                },
                // 饼图文本标签
                label: {
                    // 是否展示文本标签
                    show: false
                },
                data: sexData
            }
        ]
    }
}

/**
 * 会员状态
 * */
// 会员状态分布
const statusOptions = ref({})
// 会员状态初始化
const initMemberStatus = () => {
    statusOptions.value = {
        tooltip: {
            trigger: 'item'
        },
        // x 轴
        xAxis: {
            type: 'category',
            data: ['沉睡', '正常', '活跃'],
            axisTick: {
                alignWithLabel: true
            }
        },
        yAxis: {
            type: 'value'
        },
        // 柱状图颜色
        color: ['#FB7F30'],
        grid: {
            left: '15%'
        },
        series: [
            {
                data: [0, 87, 26],
                type: 'bar',
                name: '会员数量',
                // 柱状图宽度
                barWidth: '25%'
            }
        ]
    }
}
</script>

<style lang="less" scoped>
.quantity-show{
    width: calc((100% - 75px) / 4);
    height: 115px;

    div:first-child{
        font-family: "Dubai Light", serif;
    }

    .iconfont {
        font-size: 65px;
    }

    .icon-wenhao{
        font-size: 20px;
    }
}

.second-container-left{
    flex: 1;
    height: 800px;
}

.second-container-right{
    width: calc((100% - 75px) / 4);

    .common-box{
        height: 800px;
    }

    .rank{

        &:first-child .rank-num{
            color: #F98A14;
        }

        &:nth-child(2) .rank-num{
            color: #73787C;
        }

        &:nth-child(3) .rank-num{
            color: #B26C43;
        }

        & img{
            width: 40px;
        }

        .rank-num{
            color: #D1D1D1;
        }

        .rank-order{
            box-shadow: 0 3px 10px rgba(0, 0, 0, .17);
            color: #222222;
            width: 40px;
            height: 40px;
            background: #F5F5F5;
        }
    }

}

.third-container-side {
    width: calc((100% - 50px) / 4);
    height: 380px;
}

.third-container-middle {
    width: calc((100% - 50px) / 2);
    height: 380px;
}

.fourth-container-side{
    width: calc((100% - 25px) / 2);
    height: 380px;
}

</style>
